home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / comm / bbs / cit_src_7H21.lha / events.c < prev    next >
C/C++ Source or Header  |  1997-07-27  |  23KB  |  879 lines

  1. /*
  2. *                               events.c
  3. *
  4. * Event handling code for Citadel.
  5. */
  6. #include "ctdl.h"
  7. /* #define EVENT_DEBUG */
  8. /*
  9. *                               history
  10. *
  11. * 91Aug16 HAW  New comment style.
  12. * 89Jan23 HAW  Version 2 of event handling.
  13. * 87Jun13 HAW  Created.
  14. */
  15. /*
  16. *                               contents
  17. *
  18. *      InitEvents()             Initialize event stuff
  19. *      eventSort()              Sorts events
  20. *      setPtrs()                Set up pointers
  21. *      DoTimeouts()             Handles timeouts
  22. */
  23. /*
  24. * Event facility description
  25. *
  26. * Not available.
  27. */
  28. /*
  29. *                               Variables
  30. */
  31. /* Internal housekeeping variables */
  32. static int    ThisDay, ThisMinute;
  33. static long   ThisSecond;
  34. static char   warned = FALSE;
  35. static long   ThisAbsolute;
  36. /* These are lists of events */
  37. typedef struct
  38.   {
  39.   SListBase List;
  40.   long      NextAbs;
  41.   long      LastAbs;
  42.   int       toReturn;
  43.  
  44.   }
  45. EventList;
  46. static EventList Types [] =
  47.   {
  48.     { { NULL, NULL, eventSort, NULL, NULL   }, -1l, -1l, TRUE  },
  49.     { { NULL, NULL, eventSort, NULL, NULL   }, -1l, -1l, FALSE },
  50.     { { NULL, NULL, eventSort, NULL, NULL   }, -1l, -1l, FALSE }
  51.   };
  52. typedef struct
  53.   {
  54.   EVENT *Evt;
  55.   long  finish;
  56.  
  57.   }
  58. EvDoorRec;
  59. static SListBase AutoDoors =
  60.   {
  61.   NULL, ChED, CmpED, free, NULL
  62.  
  63.   };
  64. static SListBase Redirected =
  65.   {
  66.   NULL, ChRed, CmpED, free, NULL
  67.  
  68.   };
  69. int ClassActive[EVENT_CLASS_COUNT];     /* which classes are active? */
  70. #define NewUserAllowed()        (ClassActive[CL_NEWUSERS_ALLOWED])
  71. #define NewUserDisAllowed()     (ClassActive[CL_NEWUSERS_DISALLOWED])
  72. static SListBase EventEnds =
  73.   {
  74.   NULL, ChkTwoNumbers, CmpTwoLong, free, NULL
  75.  
  76.   };
  77. /*
  78. * This list helps solve the 'cheating downloader' problem.  We keep a list
  79. * of downloaders and the amount of time spent downloading.  This list is
  80. * cleared whenever the limit changes; thus, it is only effective during the
  81. * duration of a specific download time limit #event.  We reference the list
  82. * every time a user logs in (see LOG.C).
  83. */
  84. SListBase DL_List =
  85.   {
  86.   NULL, ChkTwoNumbers, CmpTwoLong, free, EatTwoNumbers
  87.  
  88.   };
  89. extern long *DL_Total;
  90. char ResolveDls = TRUE;
  91. char *DlMsgPtr = NULL;
  92. static EVENT *Cur;
  93. /* Externally needed variables */
  94. char   ForceNet = FALSE;        /* True IFF ^A has been pressed         */
  95. long   DeadTime;                /* Useful to keep this as a local       */
  96. long   AnyNetLen;               /* Same here, tonto                     */
  97. MULTI_NET_DATA AnyTimeNets;
  98. long Door_Limit;
  99. extern EVENT  *EventTab;
  100. extern MessageBuffer msgBuf;
  101. extern CONFIG cfg;
  102. extern char   outFlag;
  103. extern char   haveCarrier;
  104. extern char   onConsole;
  105. extern char   whichIO;          /* where is the I/O?            */
  106. extern char   justLostCarrier;
  107. extern char   ExitToMsdos;
  108. extern int    exitValue;
  109. extern long   Dl_Limit;    /* Yuck, but necessary */
  110. void SetAbs(EventList *list, long LastAbs);
  111.  
  112. void ShowTW(TwoNumbers *);
  113. void ExamineEvent(EVENT *);
  114. static char *cl[] =
  115.   {
  116.   "network", "extern", "relative", "dl-time", "anytime-net",
  117.   "doors-limit", "autodoor", "chat-on", "chat-off", "redirect",
  118.   "new-users-allowed", "new-users-disallowed", "until-done"
  119.  
  120.   };
  121. static char *ty[] =
  122.   {
  123.   "preempt", "non-preempt", "quiet"
  124.  
  125.   };
  126. static char *dy[] =
  127.   {
  128.   "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
  129.  
  130.   };
  131.  
  132.  
  133. /*
  134. * InitEvents()
  135. *
  136. * This function initializes events stuff.  This boils down to placing the
  137. * various events into their types (implemented in SListBase structures), which
  138. * automatically sorts them as they are added based on how close they are to
  139. * the time they are supposed to occur.
  140. */
  141. void InitEvents()
  142.   {
  143.   int      i;
  144.   InitEvTimes();
  145.   zero_array(ClassActive);              /* all classes off for now      */
  146.   for (i = 0; i < cfg.EvNumber; i++)
  147.     {
  148.     if (EventTab[i].EvClass == CLREL)
  149.       {
  150.       EventTab[i].EvMinutes =
  151.       (ThisMinute + EventTab[i].EvDur) % 10080;
  152.  
  153.       }
  154.     AddData(&Types[EventTab[i].EvType].List, EventTab + i, NULL, FALSE);
  155.  
  156.     }
  157.   SetAbs(&Types[0], -1l);
  158.   SetAbs(&Types[1], -1l);
  159.   SetAbs(&Types[2], -1l);
  160.  
  161.   }
  162. /*
  163. * InitEvTimes()
  164. *
  165. * This function initializes various time-based global variables for use by
  166. * the event stuff.
  167. */
  168. void InitEvTimes()
  169.   {
  170.   int      yr, dy, hr, mn, mon, secs, milli;
  171.   long     temp;
  172.   getRawDate(&yr, &mon, &dy, &hr, &mn, &secs, &milli);
  173.   ThisDay = WhatDay();
  174.   ThisMinute = (ThisDay * 1440) + (hr * 60) + mn;
  175.   temp = (long) ThisMinute;
  176.   ThisSecond = (temp * 60l) + secs;
  177.   ThisAbsolute = CurAbsolute();
  178.  
  179.   }
  180. /*
  181. * eventSort()
  182. *
  183. * This helps sort a list of events (a type implementation) based on how soon
  184. * each event is to occur.
  185. */
  186. int eventSort(EVENT *s1, EVENT *s2)
  187.   {
  188.   if (during(s1) && during(s2))  return (int) (s1->EvMinutes - s2->EvMinutes);
  189.   if (during(s1)) return -1;
  190.   if (during(s2)) return 1;
  191.   if ((passed(s1) && passed(s2)) ||
  192.   (!passed(s1) && !passed(s2)))  return (int)(s1->EvMinutes - s2->EvMinutes);
  193.   return (int) (s2->EvMinutes - s1->EvMinutes);
  194.  
  195.   }
  196. /*
  197. * during()
  198. *
  199. * Are we "during" this event?  This question is answered by checking to see
  200. * if this event's time period (beginning to beginning+duration) encompasses
  201. * the current time (within the week period).  The code is slightly more
  202. * complex than might be otherwise expected due to the rollover point at the
  203. * end of a week (Saturday).
  204. */
  205. int during(EVENT *x)
  206.   {
  207.   int result;
  208.   result = FALSE;
  209.   if (ThisMinute >= x->EvMinutes && ThisMinute < x->EvMinutes + x->EvDur)
  210.     {
  211.     result = TRUE;
  212.     }
  213.   else
  214.     {
  215.     if (x->EvMinutes + x->EvDur > 10080
  216.       && ThisMinute < (x->EvMinutes + x->EvDur) % 10080)
  217.       {
  218.       result = TRUE;
  219.       };
  220.     };
  221.   return result;
  222.  
  223.   }
  224. /*
  225. * passed()
  226. *
  227. * This function determines if this event's start time has passed in terms of
  228. * the week.
  229. */
  230. int passed(EVENT *x)
  231.   {
  232.   if ((x->EvDur == 0 && x->EvMinutes <= ThisMinute) ||
  233.   (x->EvDur != 0 && x->EvMinutes < ThisMinute))  return TRUE;
  234.   return FALSE;
  235.  
  236.   }
  237. /*
  238. * SetAbs()
  239. *
  240. * This function calculates when the next event is supposed to occur for the
  241. * given type.  This is calculated in terms of absolute time, making later
  242. * comparisons much easier to deal with.  Since it's possible that this
  243. * function will be called when we're actually already into some event's
  244. * period, we have to take this into account.  That should explain the check
  245. * for during() at the end of the function.
  246. */
  247. void SetAbs(EventList *list, long LowLimit)
  248.   {
  249.   long temp, InSeconds;
  250.   if ((Cur = (EVENT *) GetFirst(&list->List)) != NULL)
  251.     {
  252.     InitEvTimes();
  253.     temp = (long) Cur->EvMinutes;
  254.     InSeconds = temp * 60l;
  255.     if (during(Cur))
  256.     list->NextAbs = ThisAbsolute - WeekDiff(ThisSecond, InSeconds);
  257.     else if (LowLimit != -1l)
  258.       {
  259.       if (ThisAbsolute - WeekDiff(ThisSecond, InSeconds) > LowLimit)
  260.       list->NextAbs = ThisAbsolute - WeekDiff(ThisSecond, InSeconds);
  261.       else
  262.       list->NextAbs = ThisAbsolute + WeekDiff(InSeconds, ThisSecond);
  263.  
  264.       }
  265.     else
  266.     list->NextAbs = ThisAbsolute + WeekDiff(InSeconds, ThisSecond);
  267.  
  268.     }
  269.  
  270.   }
  271. /*
  272. * WeekDiff()
  273. *
  274. * This function figures out difference in time between events, taking into
  275. * account the week rollover stuff.  The difference is returned in seconds.
  276. */
  277. long WeekDiff(long future, long now)
  278.   {
  279.   long diff;
  280.   if( cfg.BoolFlags.debug )
  281.     {
  282.     splitF(NULL,"WeekDiff(future:%ld, now:%ld) =",future, now);
  283.     };
  284.   diff = (long)( ( now > future) ? (604800l - now + future ) : ( future - now) );
  285.   if( cfg.BoolFlags.debug )
  286.     {
  287.     splitF(NULL,"%ld\n",diff);
  288.     };
  289.   return diff;
  290.   }
  291. /*
  292. * ChkPreempt()
  293. *
  294. * This function will estimate whether the time to d/l will interfere with
  295. * the next preemptive event.  If it does, then the warning string associated
  296. * with this preemptive event is returned.  If there is no collision then
  297. * NULL is returned.
  298. */
  299. char *ChkPreempt(long estimated)
  300.   {
  301.   if ((Cur = GetFirst(&Types[0].List)) != NULL)
  302.     {
  303.     if (Types[0].NextAbs - CurAbsolute() < estimated)
  304.     return (char *)(cfg.codeBuf + Cur->EvWarn);
  305.  
  306.     }
  307.   return NULL;          /* No preemptive events to worry about */
  308.  
  309.   }
  310. /*
  311. * CheckAutoDoor()
  312. *
  313. * This function checks to see if the given login name has an autodoor that
  314. * should be executed.  It returns -1 if no such autodoor exists, otherwise
  315. * it returns the EvExitVal value associated with the autodoor entry.  This
  316. * function resides in here rather than the door source because autodoors
  317. * are implemented as #events.
  318. */
  319. int CheckAutoDoor(char *name)
  320.   {
  321.   EvDoorRec rec;
  322.   rec.Evt = GetDynamic(sizeof (EVENT)); /* get around possible bug */
  323.   strCpy(rec.Evt->vars.EvUserName, name);
  324.   if ((Cur = SearchList(&AutoDoors, &rec)) != NULL)
  325.     {
  326.     free(rec.Evt);
  327.     return (int) Cur->EvExitVal;
  328.  
  329.     }
  330.   free(rec.Evt);
  331.   return ERROR;
  332.  
  333.   }
  334. /*
  335. * DoTimeouts()
  336. *
  337. * This is the function responsible for actual checking of timeouts.  It
  338. * returns TRUE if you want modIn to break out, too.  It should only be called
  339. * from modIn().
  340. */
  341. char DoTimeouts()
  342.   {
  343.   int  yr, dy, hr, mn, temp, mon, secs, milli;
  344.   #ifdef SYSTEM_CLOCK
  345.   static int LastMinute = -1;
  346.   #endif
  347.   extern int PriorityMail;
  348.   TwoNumbers *tmp;
  349.   EvDoorRec  *evtmp;
  350.   extern SListBase UntilNetSessions;
  351.   getRawDate(&yr, &mon, &dy, &hr, &mn, &secs, &milli);
  352.   #ifdef SYSTEM_CLOCK
  353.   if (LastMinute != mn || ForceNet )
  354.     {
  355.     ScrTimeUpdate(hr, mn);
  356.     LastMinute = mn;
  357.  
  358.     }
  359.   else
  360.     {
  361.     BeNice(INUSE_PAUSE);  /* check for ARexx input and sleep */
  362.     };
  363.   #endif
  364.   ThisMinute = (WhatDay() * 1440) + (hr * 60) + mn;
  365.   ThisAbsolute = (long) ThisMinute;
  366.   ThisSecond = ThisAbsolute * 60 + secs;
  367.   ThisAbsolute = CurAbsolute();
  368.   /* First we deal with events which are deactivating */
  369.   if ((tmp = GetFirst(&EventEnds)) != NULL)
  370.     {
  371.     if (ThisAbsolute >= tmp->second)
  372.       {
  373.       /* event is ending! */
  374.       ClassActive[tmp->first] = FALSE;
  375.       KillData(&EventEnds, tmp);                /* take it off the list */
  376.       if (tmp->first == CL_DL_TIME)
  377.       ResolveDLStuff();
  378.  
  379.       }
  380.  
  381.     }
  382.   if ((evtmp = GetFirst(&AutoDoors)) != NULL)
  383.     {
  384.     if (ThisAbsolute >= evtmp->finish)
  385.       {
  386.       /* autodoor finish */
  387.       KillData(&AutoDoors, evtmp);
  388.  
  389.       }
  390.  
  391.     }
  392.   if ((evtmp = GetFirst(&Redirected)) != NULL)
  393.     {
  394.     if (ThisAbsolute >= evtmp->finish)
  395.       {
  396.       /* redirection finish */
  397.       KillData(&Redirected, evtmp);
  398.  
  399.       }
  400.  
  401.     }
  402.   /* Next we deal with preemptive events, which are Type 0 */
  403.   /* give a warning at T-5 */
  404.   if ((Cur = GetFirst(&Types[0].List)) != NULL &&
  405.   !warned && Types[0].NextAbs - ThisAbsolute < 300l && onLine())
  406.     {
  407.     temp = Cur->EvMinutes % 1440;
  408.     warned = TRUE;
  409.     outFlag = IMPERVIOUS;
  410.     Output_Citadel_Message("ESYSDN",temp/60,temp%60,(long)Cur->EvWarn+(long)cfg.codeBuf);
  411.     outFlag = OUTOK;
  412.     return (char)FALSE;
  413.  
  414.     }
  415.   else if (Cur != NULL && Types[0].NextAbs < ThisAbsolute)
  416.     {
  417.     if (onLine())
  418.       {
  419.       /* first boot off user, next time do event */
  420.       outFlag = IMPERVIOUS;
  421.       Output_Citadel_Message("EVHAPP",(long)Cur->EvWarn + (long)cfg.codeBuf, NULL, NULL);
  422.       if (onConsole)
  423.         {
  424.         /* Ugly cheat */
  425.         onConsole = FALSE;
  426.         whichIO = MODEM;
  427.         justLostCarrier = TRUE;
  428.         EnableModem(FALSE);
  429.  
  430.         }
  431.       else
  432.       HangUp(FALSE);
  433.       outFlag = OUTOK;
  434.       return (char)TRUE;
  435.  
  436.       }
  437.     return (char)FigureEvent(0);
  438.  
  439.     }
  440.   if (!onLine() && (Cur = GetFirst(&Types[1].List)) != NULL &&
  441.   Types[1].NextAbs < ThisAbsolute)
  442.   return (char)FigureEvent(1);
  443.   if ((Cur = GetFirst(&Types[2].List)) != NULL &&
  444.   Types[2].NextAbs < ThisAbsolute)
  445.   return (char)FigureEvent(2);
  446.   /* check priority mail -- odd place for the check, but wotthehell */
  447.   if (PriorityMail)
  448.     {
  449.     if (!onLine())
  450.       {
  451.       netController((hr*60) + mn, 0, PRIORITY_MAIL, ANYTIME_NET, 0);
  452.       PriorityMail = 0;
  453.  
  454.       }
  455.  
  456.     }
  457.   /* handle anytime netting here - is special type of thing */
  458.   if (chkTimeSince(NEXT_ANYNET) > DeadTime || ForceNet)
  459.     {
  460.     if (ClassActive[CL_ANYTIME_NET])
  461.       {
  462.       if (!onLine())
  463.         {
  464.         netController((hr * 60) + mn, AnyNetLen,
  465.         AnyTimeNets, ANYTIME_NET, 0);
  466.         ScrNewUser();
  467.         ForceNet = FALSE;
  468.  
  469.         }
  470.  
  471.       }
  472.     else ForceNet = FALSE;
  473.     startTimer(NEXT_ANYNET);
  474.  
  475.     }
  476.   /*
  477.   * now see if we have any other net sessions due to be run.  These are
  478.   * sessions scheduled by the user from the Net menu. If so, run each of
  479.   * them by killing the list (the kill function should run each).
  480.   */
  481.   if (!onLine() && GetFirst(&UntilNetSessions) != NULL)
  482.     {
  483.     KillList(&UntilNetSessions);
  484.  
  485.     }
  486.   return (char)ExitToMsdos;
  487.  
  488.   }
  489. /*
  490. * ResolveDLStuff()
  491. *
  492. * Resolves the DL list when a limit changes.  Basically, we clear the list of
  493. * all users, but if someone is currently on, we wish to retain the user's
  494. * record.  So, we make a copy of it, clear the list, and then restore the
  495. * user's record to the list.  This code and related code elsewhere should
  496. * help minimize the 'cheating user' problem.
  497. */
  498. void ResolveDLStuff()
  499.   {
  500.   TwoNumbers  *tmp = NULL;
  501.   extern int  thisLog;  /* entry currently in logBuf    */
  502.   extern char loggedIn;
  503.   if (!ResolveDls)
  504.     {
  505.     ResolveDls = TRUE;
  506.     return;
  507.  
  508.     }
  509.   if (loggedIn)         /* this makes a copy if someone is on */
  510.   tmp = MakeTwo(thisLog, *DL_Total);
  511.   KillList(&DL_List);           /* Now clear the list           */
  512.   if (tmp != NULL)
  513.     {
  514.     /* If someone is on, re-add to the list */
  515.     AddData(&DL_List, tmp, NULL, TRUE);
  516.     DL_Total = &tmp->second;    /* And keep pointing    */
  517.  
  518.     }
  519.  
  520.   }
  521. /*
  522. * FigureEvent()
  523. *
  524. * This function handles an event becoming active and takes action.
  525. */
  526. int FigureEvent(int index)
  527.   {
  528.   long ThisAbs, temp, InSeconds, EndIt = -1l, CalcEnd;
  529.   EvDoorRec *EvDoor;
  530.   if( cfg.BoolFlags.debug )
  531.     {
  532.     splitF(NULL," Event Type - %d", index);
  533.     splitF(NULL," Class:%s Type:%s\n ", cl[Cur->EvClass], ty[Cur->EvType]);
  534.     splitF(NULL,"%s -  ", dy[Cur->EvMinutes / 1440]);
  535.     temp = Cur->EvMinutes % 1440;
  536.     splitF(NULL,"%d:%02d %d %lx\n", temp/60, temp%60, Cur->EvDur, Cur->EvExitVal);
  537.     };
  538.   temp = (long) Cur->EvMinutes;
  539.   InSeconds = temp * 60l;
  540.   ThisAbs = ThisAbsolute - WeekDiff(ThisSecond, InSeconds);
  541.   CalcEnd = ThisAbs + (Cur->EvDur * 60l);
  542.   if( cfg.BoolFlags.debug )
  543.     {
  544.     splitF(NULL," Event ThisABS: %ld CalcEnd: %ld ThisSec:%ld Insec:%ld\n"
  545.     ,ThisAbs, CalcEnd, ThisSecond, InSeconds);
  546.     };
  547.   switch (Cur->EvClass)
  548.     {
  549.     case CL_UNTIL_NET:
  550.     case CLNET:
  551.     if( cfg.BoolFlags.debug )
  552.       {
  553.       splitF(NULL," Event CL_UNTIL_NET/CLNET\n");
  554.       };
  555.     netController(Cur->EvMinutes % 1440, Cur->EvDur, Cur->EvExitVal,
  556.     (Cur->EvClass == CLNET) ? NORMAL_NET : UNTIL_NET,
  557.     REPORT_FAILURE | LEISURELY);
  558.     warned = FALSE;
  559.     startTimer(NEXT_ANYNET);
  560.     break;
  561.     case CLEXTERN:
  562.     case CLREL:
  563.     if( cfg.BoolFlags.debug )
  564.       {
  565.       splitF(NULL," Event CLEXTERN/CLREL\n");
  566.       };
  567.     ExitToMsdos = TRUE;
  568.     exitValue = (int) Cur->EvExitVal;
  569.     return TRUE;        /* force it */
  570.     case CL_DL_TIME:
  571.     if( cfg.BoolFlags.debug )
  572.       {
  573.       splitF(NULL," Event CL_DL_TIME\n");
  574.       };
  575.     EndIt = CalcEnd;
  576.     Dl_Limit = Cur->EvExitVal;
  577.     ResolveDLStuff();
  578.     DlMsgPtr = cfg.codeBuf + Cur->EvWarn;
  579.     break;
  580.     case CL_ANYTIME_NET:
  581.     if( cfg.BoolFlags.debug )
  582.       {
  583.       splitF(NULL," Event CL_ANYTIME_NET\n");
  584.       };
  585.     EndIt = CalcEnd;
  586.     /* gets eligible nets */
  587.     AnyTimeNets = Cur->EvExitVal;
  588.     DeadTime    = Cur->vars.Anytime.EvDeadTime;
  589.     AnyNetLen   = Cur->vars.Anytime.EvAnyDur;
  590.     break;
  591.     case CL_DOOR_TIME:
  592.     if( cfg.BoolFlags.debug )
  593.       {
  594.       splitF(NULL," Event CL_DOOR_TIME\n");
  595.       };
  596.     EndIt = CalcEnd;
  597.     Door_Limit = Cur->EvExitVal;
  598.     break;
  599.     case CL_AUTODOOR:
  600.     case CL_REDIRECT:
  601.     if( cfg.BoolFlags.debug )
  602.       {
  603.       splitF(NULL," Event CL_AUTODOOR/REDIRECT\n");
  604.       };
  605.     EvDoor = GetDynamic(sizeof *EvDoor);
  606.     EvDoor->Evt = Cur;
  607.     EvDoor->finish = CalcEnd;
  608.     AddData((Cur->EvClass == CL_AUTODOOR) ? &AutoDoors : &Redirected,
  609.     EvDoor, NULL, TRUE);
  610.     break;
  611.     case CL_CHAT_ON:
  612.     case CL_CHAT_OFF:
  613.     if( cfg.BoolFlags.debug )
  614.       {
  615.       splitF(NULL," Event CL_CHAT_ON/OFF\n");
  616.       };
  617.     cfg.BoolFlags.noChat = (Cur->EvClass != CL_CHAT_ON);
  618.     ScrNewUser();
  619.     break;
  620.     case CL_NEWUSERS_ALLOWED:
  621.     case CL_NEWUSERS_DISALLOWED:
  622.     if( cfg.BoolFlags.debug )
  623.       {
  624.       splitF(NULL," Event CL_NEW_USERS_ALLOWED/DISALLOWED\n");
  625.       };
  626.     cfg.BoolFlags.unlogLoginOk = (Cur->EvClass == CL_NEWUSERS_ALLOWED);
  627.     EndIt = CalcEnd;
  628.     break;
  629.     case CL_NETCACHE:
  630.     if( cfg.BoolFlags.debug )
  631.       {
  632.       splitF(NULL," Event CL_NETCACHE\n");
  633.       };
  634.     CacheMessages(Cur->EvExitVal, FALSE);
  635.     break;
  636.     default:    /* do nothing */
  637.     if( cfg.BoolFlags.debug )
  638.       {
  639.       splitF(NULL," Event:Unknown \n");
  640.       };
  641.  
  642.     };
  643.   if (EndIt != -1l)
  644.     {
  645.     AddData(&EventEnds, MakeTwo(Cur->EvClass, EndIt), NULL, TRUE);
  646.     ClassActive[Cur->EvClass] = TRUE;       /* turn it on, baby! */
  647.  
  648.     };
  649.   FrontToEnd(&Types[index].List);       /* put event on end of list */
  650.   Types[index].LastAbs = ThisAbs;
  651.   SetAbs(&Types[index], Types[index].LastAbs);
  652.   return Types[index].toReturn;
  653.  
  654.   }
  655. /*
  656. * ActiveEvents()
  657. *
  658. * This puts together something vaguely resembling a useful list of currently
  659. * active events.
  660. */
  661. void ActiveEvents(char *buf)
  662.   {
  663.   int i;
  664.   sPrintf(lbyte(buf), "\n   Active Event,s:\n ");
  665.   if (Dl_Limit_On())                sPrintf(lbyte(buf), "D-L time limit of %ld minutes.\n ", Dl_Limit);
  666.   if (Door_Limit_On())              sPrintf(lbyte(buf), "Door time limit of %ld minutes.\n ", Door_Limit);
  667.   if (GetFirst(&Redirected) != NULL)sPrintf(lbyte(buf), "%d Redirect Files active.\n ",  RunList(&Redirected, NoFree));
  668.   if (GetFirst(&AutoDoors) != NULL) sPrintf(lbyte(buf), "%d Auto Doors active.\n ", RunList(&AutoDoors, NoFree));
  669.   if (NewUserAllowed())             sPrintf(lbyte(buf), "New Users Allowed event active.\n ");
  670.   if (NewUserDisAllowed())          sPrintf(lbyte(buf), "New Users Disallowed event active.\n ");
  671.   if (ClassActive[CL_ANYTIME_NET])
  672.     {
  673.     sPrintf(lbyte(buf), "Anytime net active for net(s) value:%08.8lX - ",AnyTimeNets);
  674.     for (i = 0; i < 32; i++)
  675.       {
  676.       if ((1l << i) & AnyTimeNets) sprintf(lbyte(buf), "%d, ", i + 1);
  677.  
  678.       };
  679.     buf[strLen(buf) - 2] = 0;
  680.     strcat(buf, ".\n ");
  681.  
  682.     }
  683.  
  684.   }
  685. /*
  686. * ForceAnytime()
  687. *
  688. * This is an interface function for forcing anytime net.
  689. */
  690. void ForceAnytime()
  691.   {
  692.   if (ClassActive[CL_ANYTIME_NET])
  693.     {
  694.     ForceNet = !ForceNet;
  695.     ScrNewUser();
  696.  
  697.     }
  698.  
  699.   }
  700. /*
  701. * ChkTwoNumbers()
  702. *
  703. * check for equality of d1 vs d2.  This is used to search a list for a
  704. * given value.
  705. */
  706. void *ChkTwoNumbers(TwoNumbers *d1, TwoNumbers *d2)
  707.   {
  708.   if (d1->first == d2->first) return &d1->second;
  709.   return NULL;
  710.  
  711.   }
  712. /*
  713. * MakeTwo()
  714. *
  715. * This creates a new record for addition to a list.
  716. */
  717. TwoNumbers *MakeTwo(int First, long Second)
  718.   {
  719.   TwoNumbers *tmp;
  720.   tmp = (TwoNumbers *) GetDynamic(sizeof *tmp);
  721.   tmp->first  = First;
  722.   tmp->second = Second;
  723.   return tmp;
  724.  
  725.   }
  726. /*
  727. * CmpTwoLong()
  728. *
  729. * This functoin compares TwoNumbers in their long parts and returns a
  730. * value suitable for use in sorting.
  731. */
  732. int CmpTwoLong(TwoNumbers *d1, TwoNumbers *d2)
  733.   {
  734.   return (d1->second < d2->second) ? -1 : 1;
  735.  
  736.   }
  737. /*
  738. * ChED()
  739. *
  740. * This function is used to search for autodoors.  If the autodoor is found
  741. * then the address to it is returned, otherwise NULL.
  742. */
  743. void *ChED(EvDoorRec *d1, EvDoorRec *d2)
  744.   {
  745.   if (strCmpU(d1->Evt->vars.EvUserName, d2->Evt->vars.EvUserName) == SAMESTRING)
  746.   return d1->Evt;
  747.   return NULL;
  748.  
  749.   }
  750. /*
  751. * ChRed()
  752. *
  753. * This function is used to search to see if a given file is on the 'redirect'
  754. * list.  Notice we check against both name and system origin.
  755. */
  756. void *ChRed(EvDoorRec *d1, EvDoorRec *d2)
  757.   {
  758.   if (strCmpU(d1->Evt->vars.Redirect.EvFilename,
  759.   d2->Evt->vars.Redirect.EvFilename) == SAMESTRING &&
  760.   strCmpU(d1->Evt->vars.Redirect.EvSystem,
  761.   d2->Evt->vars.Redirect.EvSystem) == SAMESTRING)
  762.   return d1->Evt;
  763.   return NULL;
  764.  
  765.   }
  766. /*
  767. * EatTwoNumbers()
  768. *
  769. * This function will eat a line of text from disk and make it into a record
  770. * for placement on a disk.  It's simply a space separated string.
  771. */
  772. void *EatTwoNumbers(char *line)
  773.   {
  774.   TwoNumbers *temp;
  775.   char *space;
  776.   if ((space = strchr(line, ' ')) == NULL)
  777.   return NULL;
  778.   temp = GetDynamic(sizeof *temp);
  779.   temp->first = atoi(line);
  780.   temp->second = atol(space + 1);
  781.   return temp;
  782.  
  783.   }
  784. /*
  785. * WrtTwoNumbers()
  786. *
  787. * This function is used to write the contents of a TwoNumbers structure to
  788. * disk.  This is used for saving information concerning a list while Citadel
  789. * is temporarily down.
  790. */
  791. void WrtTwoNumbers(TwoNumbers *d)
  792.   {
  793.   extern FILE *upfd;
  794.   fprintf(upfd, "%d %d\n", d->first, d->second);
  795.  
  796.   }
  797. /*
  798. * CmpED()
  799. *
  800. * This function is used to sort a list of autodoors based on when they finish.
  801. */
  802. int CmpED(EvDoorRec *d1, EvDoorRec *d2)
  803.   {
  804.   return (d1->finish < d2->finish) ? -1 : 1;
  805.  
  806.   }
  807. /*
  808. * RedirectFile()
  809. *
  810. * This function is used to discover if the given file should be redirected from
  811. * the normal file reception area to somewhere else.
  812. *
  813. * If it should be then a pointer is returned to a string representing the new
  814. * location; otherwise, NULL is returned.
  815. */
  816. char *RedirectFile(char *filename, char *systemname)
  817.   {
  818.   EvDoorRec rec;
  819.   rec.Evt = GetDynamic(sizeof (EVENT)); /* get around possible bug */
  820.   /* prepare for search */
  821.   strCpy(rec.Evt->vars.Redirect.EvFilename, filename);
  822.   strCpy(rec.Evt->vars.Redirect.EvSystem, systemname);
  823.   Cur = SearchList(&Redirected, &rec);
  824.   free(rec.Evt);
  825.   return(char *)( (Cur != NULL) ? cfg.codeBuf + Cur->vars.Redirect.EvHomeDir : NULL);
  826.  
  827.   }
  828. /***********************************************************/
  829. void EventShow()
  830.   {
  831.   int i;
  832.   mPrintf("\nCurAbs=%ld\n ", CurAbsolute());
  833.   mPrintf("ANYTIME NET is %d\n ", ClassActive[CL_ANYTIME_NET]);
  834.   mPrintf("non-preempt nextabs is %ld, %ld seconds away\n ",
  835.   Types[2].NextAbs, Types[2].NextAbs - CurAbsolute());
  836.   mPrintf("Preemptive list (%ld):\n ", Types[0].NextAbs);
  837.   RunList(&Types[0].List, ExamineEvent);
  838.   modIn();
  839.   mPrintf("Non-Preemptive list (%ld):\n ", Types[1].NextAbs);
  840.   RunList(&Types[1].List, ExamineEvent);
  841.   modIn();
  842.   mPrintf("Quiet list (%ld):\n ", Types[2].NextAbs);
  843.   RunList(&Types[2].List, ExamineEvent);
  844.   modIn();
  845.   mPrintf("Event ending list:\n ");
  846.   RunList(&EventEnds, ShowTW);
  847.   mPrintf("Anytime net is %s\n ", (ClassActive[CL_ANYTIME_NET]) ? "On" : "Off");
  848.   if (ClassActive[CL_ANYTIME_NET])
  849.     {
  850.     msgBuf.mbtext[0] = 0;
  851.     for (i = 0; i < 32; i++)
  852.     if ((1l << i) & AnyTimeNets)
  853.     sprintf(lbyte(msgBuf.mbtext), "%d, ", i + 1);
  854.     if (strlen(msgBuf.mbtext))
  855.     msgBuf.mbtext[strLen(msgBuf.mbtext) - 2] = 0;
  856.     mPrintf("Anytime nets: %s\n ", msgBuf.mbtext);
  857.  
  858.     }
  859.  
  860.   }
  861. void ShowTW(tw)
  862. TwoNumbers *tw;
  863.   {
  864.   mPrintf("Class %s active, shuts down @%ld\n ", cl[tw->first],
  865.   tw->second);
  866.  
  867.   }
  868. void ExamineEvent(ev)
  869. EVENT *ev;
  870.   {
  871.   int temp;
  872.   mPrintf("%s %s ", cl[ev->EvClass], ty[ev->EvType]);
  873.   mPrintf("%s ", dy[ev->EvMinutes / 1440]);
  874.   temp = ev->EvMinutes % 1440;
  875.   mPrintf("%d:%02d %d %lx\n ", temp/60, temp%60, ev->EvDur,
  876.   ev->EvExitVal);
  877.  
  878.   }
  879.